package com.aponisipsis.gl3d.data;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.util.Collection;
import java.util.HashMap;

import org.newdawn.slick.opengl.Texture;
import org.newdawn.slick.opengl.TextureLoader;

import com.aponisipsis.gl3d.geometry.Material;
import com.aponisipsis.gl3d.geometry.Mesh2D;
import com.aponisipsis.gl3d.geometry.Model;
import com.aponisipsis.gl3d.geometry.TextureUnit;
import com.aponisipsis.gl3d.importer.ResourceLoader;
import com.aponisipsis.gl3d.importer.json.JSONLoader;
import com.aponisipsis.gl3d.importer.json.JSONMaterialData;
import com.aponisipsis.gl3d.importer.json.JSONMeshData;

import com.aponisipsis.gl3d.importer.json.JSONSceneData;

public class ResourceManager {
	private final static HashMap<String, Model> models;
	private final static HashMap<String, Mesh2D> meshes;
	private final static HashMap<String, Material> materials;
	private final static HashMap<String, Texture> textures;
	
	private final static ResourceLoader resourceLoader;
	
	static{
		resourceLoader = new JSONLoader();
		models = new HashMap<String, Model>();
		meshes = new HashMap<String, Mesh2D>();
		materials = new HashMap<String, Material>();
		textures = new HashMap<String, Texture>();
	}

	private static InputStream getResource(String resource){
		File file = new File(resource);
		if(file.exists()){
			try {
				return new FileInputStream(file);
			} catch (FileNotFoundException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
				return null;
			}
		}else{
			return ResourceManager.class.getResourceAsStream(resource);
		}
	}
	
//	public static Model loadModel(String resource) throws Exception{
//		if(!models.containsKey(resource)){
//			
//			JSONModelData data = resourceLoader.load(getResource(resource),JSONModelData.class);
//			
//			
//			Model model = new Model();
//			model.setMaterial(loadMaterial(data.material));
//			model.setMesh(loadMesh(data.mesh));
//			//model.setTexture(loadTexture(data.texture_map));
//			
//			
//			models.put(resource, model);
//		}
//		
//		return models.get(resource);
//	}
	
	public static Mesh2D loadMesh(String resource){
		if(!meshes.containsKey(resource)){
			JSONMeshData data = resourceLoader.load(getResource(resource),JSONMeshData.class);
			
			meshes.put(resource,data.toMesh());
		}
		
		return meshes.get(resource);
	}

//	public static Material loadMaterial(String resource) throws Exception{
//		if(!materials.containsKey(resource)){
//
//			JSONMaterialData mdat = resourceLoader.load(getResource(resource), JSONMaterialData.class);
//			
//			Material material = mdat.toMaterial();
//			for(JSONMaterialTextureData jmtd:mdat.textures){
//				loadTexture(jmtd.name, jmtd.image);
//				//material.addTextureMap(jmtd.uvmap, jmtd.name);
//			}
//			materials.put(resource, mdat.toMaterial());
//			System.out.printf("Material %s loaded\n",mdat.name);
//		}
//		
//		return materials.get(resource);
//	}
	
	public static void loadScene(String resource){
		JSONSceneData sdat = resourceLoader.load(getResource(resource), JSONSceneData.class);
		
		// Clear resources
		textures.clear();
		meshes.clear();
		materials.clear();
		
		
		for(JSONMeshData m:sdat.meshes){
			Mesh2D mesh = m.toMesh();
			mesh.getTransform().translate(m.location[0], m.location[1], m.location[2]);
			meshes.put(m.name, mesh);
		}
		for(JSONMaterialData m:sdat.materials){
			if(!textures.containsKey(m.texture_name)){
				loadTexture(m.texture_name, m.texture_file);
			}
		}
	}
	
	public static void main(String[] args) throws Exception {
		//System.out.println(loadMaterial("/assets/materials/material1.json"));
		//ResourceManager.loadModel("/assets/models/model1.json");
	}
//	
	public static Texture loadTexture(String id, String path){
		if(!textures.containsKey(id)){
			String format = path.substring(path.lastIndexOf(".")+1);
			Texture t;
			try {
				System.out.println(String.format("Loading texture %s id %s format %s\n",path,id,format));
				t = TextureLoader.getTexture(format, getResource(path),true);
				textures.put(id, t);
				
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		
		return textures.get(id);
	}
	
	public static Mesh2D getMesh(String id){ return meshes.get(id); }
	public static Material getMaterial(String id){ return materials.get(id); }
	public static Texture getTexture(String id){ return textures.get(id); }
	
	public static Collection<Mesh2D> getAllMeshes(){
		return meshes.values();
	}
}
